textview: Only create cairo context in gtktextdisplay.c
authorBenjamin Otte <otte@redhat.com>
Sat, 14 Jul 2018 03:26:33 +0000 (05:26 +0200)
committerBenjamin Otte <otte@redhat.com>
Sat, 14 Jul 2018 03:27:54 +0000 (05:27 +0200)
Everything else is done using GtkSnapshot now, including renaming the
draw_layer vfunc to snapshot_layer.

demos/widget-factory/widget-factory.c
gtk/gtktextdisplay.c
gtk/gtktextdisplayprivate.h
gtk/gtktextutil.c
gtk/gtktextview.c
gtk/gtktextview.h
tests/testtextview.c

index d0e2cafbb15d8b6d25751759eceba06fd547d05e..e0027e97f0a6e5bd8ed89e4afffc7fe80c834075 100644 (file)
@@ -1080,7 +1080,7 @@ set_accel (GtkApplication *app, GtkWidget *widget)
 typedef struct
 {
   GtkTextView tv;
-  GdkPixbuf *pixbuf;
+  GdkTexture *texture;
 } MyTextView;
 
 typedef GtkTextViewClass MyTextViewClass;
@@ -1093,18 +1093,23 @@ my_text_view_init (MyTextView *tv)
 }
 
 static void
-my_tv_draw_layer (GtkTextView      *widget,
-                  GtkTextViewLayer  layer,
-                  cairo_t          *cr)
+my_tv_snapshot_layer (GtkTextView      *widget,
+                      GtkTextViewLayer  layer,
+                      GtkSnapshot      *snapshot)
 {
   MyTextView *tv = (MyTextView *)widget;
 
-  if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->pixbuf)
+  if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->texture)
     {
-      cairo_save (cr);
-      gdk_cairo_set_source_pixbuf (cr, tv->pixbuf, 0.0, 0.0);
-      cairo_paint_with_alpha (cr, 0.333);
-      cairo_restore (cr);
+      gtk_snapshot_push_opacity (snapshot, 0.333);
+      gtk_snapshot_append_texture (snapshot,
+                                   tv->texture,
+                                   &GRAPHENE_RECT_INIT(
+                                     0, 0,
+                                     gdk_texture_get_width (tv->texture),
+                                     gdk_texture_get_height (tv->texture)
+                                   ));
+      gtk_snapshot_pop (snapshot);
     }
 }
 
@@ -1113,7 +1118,7 @@ my_tv_finalize (GObject *object)
 {
   MyTextView *tv = (MyTextView *)object;
 
-  g_clear_object (&tv->pixbuf);
+  g_clear_object (&tv->texture);
 
   G_OBJECT_CLASS (my_text_view_parent_class)->finalize (object);
 }
@@ -1125,20 +1130,24 @@ my_text_view_class_init (MyTextViewClass *class)
   GObjectClass *o_class = G_OBJECT_CLASS (class);
 
   o_class->finalize = my_tv_finalize;
-  tv_class->draw_layer = my_tv_draw_layer;
+  tv_class->snapshot_layer = my_tv_snapshot_layer;
 }
 
 static void
 my_text_view_set_background (MyTextView *tv, const gchar *filename)
 {
   GError *error = NULL;
+  GFile *file;
 
-  g_clear_object (&tv->pixbuf);
+  g_clear_object (&tv->texture);
 
   if (filename == NULL)
     return;
 
-  tv->pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+  file = g_file_new_for_path (filename);
+  tv->texture = gdk_texture_new_from_file (file, &error);
+  g_object_unref (file);
+
   if (error)
     {
       g_warning ("%s", error->message);
index 1e935012edf0405fb6cc774bb02a6df34610945a..066bcef121b0be3f7666e9cd72e1dd98eedabd2e 100644 (file)
@@ -816,9 +816,10 @@ get_text_renderer (void)
 }
 
 void
-gtk_text_layout_draw (GtkTextLayout *layout,
-                      GtkWidget *widget,
-                      cairo_t *cr)
+gtk_text_layout_snapshot (GtkTextLayout      *layout,
+                          GtkWidget          *widget,
+                          GtkSnapshot        *snapshot,
+                          const GdkRectangle *clip)
 {
   GtkStyleContext *context;
   gint offset_y;
@@ -827,23 +828,22 @@ gtk_text_layout_draw (GtkTextLayout *layout,
   gboolean have_selection;
   GSList *line_list;
   GSList *tmp_list;
-  GdkRectangle clip;
+  cairo_t *cr;
 
   g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
   g_return_if_fail (layout->default_style != NULL);
   g_return_if_fail (layout->buffer != NULL);
-  g_return_if_fail (cr != NULL);
-
-  if (!gdk_cairo_get_clip_rectangle (cr, &clip))
-    return;
+  g_return_if_fail (snapshot != NULL);
 
   context = gtk_widget_get_style_context (widget);
 
-  line_list = gtk_text_layout_get_lines (layout, clip.y, clip.y + clip.height, &offset_y);
+  line_list = gtk_text_layout_get_lines (layout, clip->y, clip->y + clip->height, &offset_y);
 
   if (line_list == NULL)
     return; /* nothing on the screen */
 
+  cr = gtk_snapshot_append_cairo (snapshot,
+                                  &GRAPHENE_RECT_INIT(clip->x, clip->y, clip->width, clip->height));
   text_renderer = get_text_renderer ();
   text_renderer_begin (text_renderer, widget, cr);
 
@@ -933,4 +933,6 @@ gtk_text_layout_draw (GtkTextLayout *layout,
   text_renderer_end (text_renderer);
 
   g_slist_free (line_list);
+
+  cairo_destroy (cr);
 }
index ce6bc7168e24a7c522823658c4a6270c77533080..e4385e5b47b0582edf55f46c804eb4c1d7373bd0 100644 (file)
@@ -86,13 +86,14 @@ G_BEGIN_DECLS
 
 /* The drawable should be pre-initialized to your preferred background.
  * widget            - Widget to grab some style info from
- * cr                - Context to render to, matrix set so that (0, 0)
+ * snapshot          - Snapshot to render to, matrix set so that (0, 0)
  *                     is the top left of the layout
+ * clip              - visible area
  */
-GDK_AVAILABLE_IN_ALL
-void gtk_text_layout_draw (GtkTextLayout        *layout,
-                           GtkWidget            *widget,
-                           cairo_t              *cr);
+void gtk_text_layout_snapshot (GtkTextLayout        *layout,
+                               GtkWidget            *widget,
+                               GtkSnapshot          *snapshot,
+                               const GdkRectangle   *clip);
 
 
 G_END_DECLS
index 0298f88f037dd8008c7cb16995d4720219155f59..9858bec5ad50ae2af4ade9f387d56705d1d3a5e9 100644 (file)
@@ -276,7 +276,6 @@ gtk_text_util_create_rich_drag_icon (GtkWidget     *widget,
   GtkTextAttributes *style;
   PangoContext      *ltr_context, *rtl_context;
   GtkTextIter        iter;
-  cairo_t           *cr;
 
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
@@ -333,12 +332,9 @@ gtk_text_util_create_rich_drag_icon (GtkWidget     *widget,
   layout_height = MIN (layout_height, DRAG_ICON_MAX_HEIGHT);
 
   snapshot = gtk_snapshot_new ();
-  cr = gtk_snapshot_append_cairo (snapshot,
-                                  &GRAPHENE_RECT_INIT (0, 0, layout_width, layout_height));
 
-  gtk_text_layout_draw (layout, widget, cr);
+  gtk_text_layout_snapshot (layout, widget, snapshot, &(GdkRectangle) { 0, 0, layout_width, layout_height });
 
-  cairo_destroy (cr);
   g_object_unref (layout);
   g_object_unref (new_buffer);
 
index 11cfecd986ceea8701573be2f7c3bb118c43e2ae..357a7cb3b7969de1bfe71863be86d773206c515c 100644 (file)
@@ -5303,8 +5303,8 @@ gtk_text_view_motion (GtkEventController *controller,
 }
 
 static void
-gtk_text_view_paint (GtkWidget      *widget,
-                     cairo_t        *cr)
+gtk_text_view_paint (GtkWidget   *widget,
+                     GtkSnapshot *snapshot)
 {
   GtkTextView *text_view;
   GtkTextViewPrivate *priv;
@@ -5335,19 +5335,24 @@ gtk_text_view_paint (GtkWidget      *widget,
           area->width, area->height);
 #endif
 
-  cairo_save (cr);
-  cairo_translate (cr, -priv->xoffset, -priv->yoffset);
+  gtk_snapshot_offset (snapshot, -priv->xoffset, -priv->yoffset);
 
-  gtk_text_layout_draw (priv->layout,
-                        widget,
-                        cr);
+  gtk_text_layout_snapshot (priv->layout,
+                            widget,
+                            snapshot,
+                            &(GdkRectangle) {
+                              priv->xoffset,
+                              priv->yoffset,
+                              gtk_widget_get_width (widget),
+                              gtk_widget_get_height (widget)
+                            });
 
-  cairo_restore (cr);
+  gtk_snapshot_offset (snapshot, priv->xoffset, priv->yoffset);
 }
 
 static void
-draw_text (GtkWidget *widget,
-           cairo_t   *cr)
+draw_text (GtkWidget   *widget,
+           GtkSnapshot *snapshot)
 {
   GtkTextView *text_view = GTK_TEXT_VIEW (widget);
   GtkTextViewPrivate *priv = text_view->priv;
@@ -5355,32 +5360,30 @@ draw_text (GtkWidget *widget,
 
   context = gtk_widget_get_style_context (widget);
   gtk_style_context_save_to_node (context, text_view->priv->text_window->css_node);
-  gtk_render_background (context, cr,
-                         -priv->xoffset, -priv->yoffset - priv->top_margin,
-                         MAX (SCREEN_WIDTH (text_view), priv->width),
-                         MAX (SCREEN_HEIGHT (text_view), priv->height));
-  gtk_render_frame (context, cr,
-                    -priv->xoffset, -priv->yoffset - priv->top_margin,
-                    MAX (SCREEN_WIDTH (text_view), priv->width),
-                    MAX (SCREEN_HEIGHT (text_view), priv->height));
+  gtk_snapshot_render_background (snapshot, context,
+                                  -priv->xoffset, -priv->yoffset - priv->top_margin,
+                                  MAX (SCREEN_WIDTH (text_view), priv->width),
+                                  MAX (SCREEN_HEIGHT (text_view), priv->height));
+  gtk_snapshot_render_frame (snapshot, context,
+                             -priv->xoffset, -priv->yoffset - priv->top_margin,
+                             MAX (SCREEN_WIDTH (text_view), priv->width),
+                             MAX (SCREEN_HEIGHT (text_view), priv->height));
   gtk_style_context_restore (context);
 
-  if (GTK_TEXT_VIEW_GET_CLASS (text_view)->draw_layer != NULL)
+  if (GTK_TEXT_VIEW_GET_CLASS (text_view)->snapshot_layer != NULL)
     {
-      cairo_save (cr);
-      cairo_translate (cr, -priv->xoffset, -priv->yoffset);
-      GTK_TEXT_VIEW_GET_CLASS (text_view)->draw_layer (text_view, GTK_TEXT_VIEW_LAYER_BELOW_TEXT, cr);
-      cairo_restore (cr);
+      gtk_snapshot_offset (snapshot, -priv->xoffset, -priv->yoffset);
+      GTK_TEXT_VIEW_GET_CLASS (text_view)->snapshot_layer (text_view, GTK_TEXT_VIEW_LAYER_BELOW_TEXT, snapshot);
+      gtk_snapshot_offset (snapshot, priv->xoffset, priv->yoffset);
     }
 
-  gtk_text_view_paint (widget, cr);
+  gtk_text_view_paint (widget, snapshot);
 
-  if (GTK_TEXT_VIEW_GET_CLASS (text_view)->draw_layer != NULL)
+  if (GTK_TEXT_VIEW_GET_CLASS (text_view)->snapshot_layer != NULL)
     {
-      cairo_save (cr);
-      cairo_translate (cr, -priv->xoffset, -priv->yoffset);
-      GTK_TEXT_VIEW_GET_CLASS (text_view)->draw_layer (text_view, GTK_TEXT_VIEW_LAYER_ABOVE_TEXT, cr);
-      cairo_restore (cr);
+      gtk_snapshot_offset (snapshot, -priv->xoffset, -priv->yoffset);
+      GTK_TEXT_VIEW_GET_CLASS (text_view)->snapshot_layer (text_view, GTK_TEXT_VIEW_LAYER_ABOVE_TEXT, snapshot);
+      gtk_snapshot_offset (snapshot, priv->xoffset, priv->yoffset);
     }
 }
 
@@ -5413,7 +5416,6 @@ gtk_text_view_snapshot (GtkWidget   *widget,
   GSList *tmp_list;
   GtkStyleContext *context;
   graphene_rect_t bounds;
-  cairo_t *cr;
 
   graphene_rect_init (&bounds,
                       0, 0,
@@ -5422,17 +5424,13 @@ gtk_text_view_snapshot (GtkWidget   *widget,
 
   gtk_snapshot_push_clip (snapshot, &bounds);
 
-  cr = gtk_snapshot_append_cairo (snapshot, &bounds);
-
   context = gtk_widget_get_style_context (widget);
 
   text_window_set_padding (GTK_TEXT_VIEW (widget), context);
 
   DV(g_print (">Exposed ("G_STRLOC")\n"));
 
-  cairo_save (cr);
-  draw_text (widget, cr); 
-  cairo_destroy (cr);
+  draw_text (widget, snapshot); 
 
   paint_border_window (GTK_TEXT_VIEW (widget), snapshot, priv->left_window, context);
   paint_border_window (GTK_TEXT_VIEW (widget), snapshot, priv->right_window, context);
index 89629948d8db8e1d221119b3dc1c20f65e19ae9b..09840f29e822e077eb3624aac25e304b9bf738c1 100644 (file)
@@ -72,7 +72,7 @@ typedef enum
  * @GTK_TEXT_VIEW_LAYER_ABOVE_TEXT: The layer rendered above the text.
  *
  * Used to reference the layers of #GtkTextView for the purpose of customized
- * drawing with the ::draw_layer vfunc.
+ * drawing with the ::snapshot_layer vfunc.
  */
 typedef enum
 {
@@ -143,7 +143,7 @@ struct _GtkTextView
  * @create_buffer: The create_buffer vfunc is called to create a #GtkTextBuffer
  *   for the text view. The default implementation is to just call
  *   gtk_text_buffer_new().
- * @draw_layer: The draw_layer vfunc is called before and after the text
+ * @snapshot_layer: The snapshot_layer vfunc is called before and after the text
  *   view is drawing its own text. Applications can override this vfunc
  *   in a subclass to draw customized content underneath or above the
  *   text. In the %GTK_TEXT_VIEW_LAYER_BELOW_TEXT and %GTK_TEXT_VIEW_LAYER_ABOVE_TEXT
@@ -177,9 +177,9 @@ struct _GtkTextViewClass
   void (* paste_clipboard)       (GtkTextView      *text_view);
   void (* toggle_overwrite)      (GtkTextView      *text_view);
   GtkTextBuffer * (* create_buffer) (GtkTextView   *text_view);
-  void (* draw_layer)            (GtkTextView      *text_view,
+  void (* snapshot_layer)        (GtkTextView      *text_view,
                                  GtkTextViewLayer  layer,
-                                 cairo_t          *cr);
+                                 GtkSnapshot      *snapshot);
   gboolean (* extend_selection)  (GtkTextView            *text_view,
                                   GtkTextExtendSelection  granularity,
                                   const GtkTextIter      *location,
index f24014f273abab37f96e719514d913675b1323f4..d746ec2419044d7fad67439dc1be5720f84d1ba2 100644 (file)
@@ -13,25 +13,25 @@ typedef struct {
 
 G_DEFINE_TYPE (MyTextView, my_text_view, GTK_TYPE_TEXT_VIEW);
 
-static void draw_background (GtkWidget *widget, cairo_t *cr);
+static void snapshot_background (GtkWidget *widget, GtkSnapshot *snapshot);
 
 static void
 my_text_view_init (MyTextView *text_view)
 {
 }
 
-static void my_text_view_draw_layer (GtkTextView       *textview,
-                                    GtkTextViewLayer   layer,
-                                    cairo_t           *cr)
+static void my_text_view_snapshot_layer (GtkTextView       *textview,
+                                         GtkTextViewLayer   layer,
+                                         GtkSnapshot       *snapshot)
 {
   if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT)
-    draw_background (GTK_WIDGET (textview), cr);
+    snapshot_background (GTK_WIDGET (textview), snapshot);
 }
 
 static void
 my_text_view_class_init (MyTextViewClass *klass)
 {
-  GTK_TEXT_VIEW_CLASS (klass)->draw_layer = my_text_view_draw_layer;
+  GTK_TEXT_VIEW_CLASS (klass)->snapshot_layer = my_text_view_snapshot_layer;
 }
 
 static void
@@ -142,51 +142,28 @@ insert_text (GtkTextBuffer *buffer)
 #define CHECK_DARK  (1.0 / 3.0)
 #define CHECK_LIGHT (2.0 / 3.0)
 
-static cairo_pattern_t *
-get_checkered (void)
-{
-  /* need to respect pixman's stride being a multiple of 4 */
-  static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
-                                   0x00, 0xFF, 0x00, 0x00 };
-  static cairo_surface_t *checkered = NULL;
-  cairo_pattern_t *pattern;
-
-  if (checkered == NULL)
-    {
-      checkered = cairo_image_surface_create_for_data (data,
-                                                       CAIRO_FORMAT_A8,
-                                                       2, 2, 4);
-    }
-
-  pattern = cairo_pattern_create_for_surface (checkered);
-  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-  cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
-
-  return pattern;
-}
-
 static void
-draw_background (GtkWidget *widget, cairo_t *cr)
+snapshot_background (GtkWidget   *widget,
+                     GtkSnapshot *snapshot)
 {
   GdkRectangle visible_rect;
-  cairo_pattern_t *pat;
-
-  cairo_save (cr);
 
   gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (widget), &visible_rect);
-  cairo_translate (cr, -visible_rect.x, -visible_rect.y);
-
-  cairo_set_source_rgb (cr, CHECK_DARK, CHECK_DARK, CHECK_DARK);
-  cairo_paint (cr);
-
-  cairo_set_source_rgb (cr, CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT);
-  cairo_scale (cr, CHECK_SIZE, CHECK_SIZE);
-
-  pat = get_checkered ();
-  cairo_mask (cr, pat);
-  cairo_pattern_destroy (pat);
 
-  cairo_restore (cr);
+  gtk_snapshot_append_color (snapshot,
+                             &(GdkRGBA) { CHECK_DARK, CHECK_DARK, CHECK_DARK, 1.0 },
+                             &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height));
+
+  gtk_snapshot_push_repeat (snapshot,
+                            &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height),
+                            &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, CHECK_SIZE * 2, CHECK_SIZE * 2));
+  gtk_snapshot_append_color (snapshot,
+                             &(GdkRGBA) { CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT, 1.0 },
+                             &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, CHECK_SIZE, CHECK_SIZE));
+  gtk_snapshot_append_color (snapshot,
+                             &(GdkRGBA) { CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT, 1.0 },
+                             &GRAPHENE_RECT_INIT(visible_rect.x + CHECK_SIZE, visible_rect.y + CHECK_SIZE, CHECK_SIZE, CHECK_SIZE));
+  gtk_snapshot_pop (snapshot);
 }
 
 int